package cn.buk.tms.entity.order.hotel;

import cn.buk.tms.entity.order.OrderApprovalInfo;
import cn.buk.tms.entity.base.BaseOrderInfo;

import java.util.*;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

/**
 * 酒店订单
 * Created by yfdai on 2018-10-14
 * @author yfdai
 */
@Entity
@Table(name = "hotel_order", uniqueConstraints = @UniqueConstraint(name = "uk_hotel_order", columnNames = {"enterprise_id", "order_no"}))
@AssociationOverrides({
        @AssociationOverride(name = "customer",
                joinColumns = @JoinColumn(name = "customer_id"),
                foreignKey = @ForeignKey(name = "fk_hotel_order_customer")
        ),
        @AssociationOverride(name = "supplier",
                joinColumns = @JoinColumn(name = "supplier_id"),
                foreignKey = @ForeignKey(name = "fk_hotel_order_supplier")
        ),
        @AssociationOverride(name = "paymentMethod",
                joinColumns = @JoinColumn(name = "payment_method_id"),
                foreignKey = @ForeignKey(name = "fk_hotel_order_payment_method")
        )
})
public class HotelOrder extends BaseOrderInfo {

    /**
     * 订单号
     */
    @NotNull
    @Size(min = 1, max = 10)
    @Column(name = "order_no", length = 10)
    private String orderNo;

    /**
     * 上级酒店订单号, 用来关联
     */
    @Column(name = "parent_order_no", length = 10)
    private String parentOrderNo;

    /**
     * 酒店订单的类型
     * 0-预订单
     * 4-退单
     */
    @Column(name = "order_type")
    private Integer hotelOrderType;

    /**
     * 酒店订单状态
     * @see cn.buk.tms.common.constant.TmsOrderConstant 酒店订单状态
     */
    private int status;


    /**
     * 付款状态(只有付款类型非记账方式时才有用）
     * 0 or null 未支付
     * 1 已收款 已支付(通过账单设置的已支付，客服操作）
     * 2 已销账 已支付（已销账，同步财务账单的状态）
     */
    @Column(name = "pay_status")
    private Integer payStatus;

    //姓名 入住日期 酒店名称 房型 价格 服务费

    /**
     * 暂留原有的方式（入住人姓名）
     */
    @Deprecated
    @Column(name="psg_name", length=50)
    private String passengerName;
    /**
     * 入住人数
     */
    @Column(name = "psg_count")
    private Integer psgCount;
    /**
     * 入住人信息
     */
    @OneToMany(mappedBy="orderInfo", cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
    private Set<HotelOrderPassenger> passengers;
    /**
     * 酒店名称
     */
    @Column(name="hotel_name", length=100)
    private String hotelName;

    /**
     * 酒店地址
     */
    @Column(name = "hotel_address", length = 200)
    private String hotelAddress;

    /**
     * 酒店信息的id(本地酒店系统）
     */
    @Column(name = "hotel_id")
    private Integer hotelId;
    /**
     * 城市id（tms维护的酒店信息）
     */
    @Column(name = "city_id")
    private Integer cityId;
    /**
     * 城市名称
     */
    @Column(name = "city_name")
    private String cityName;
    /**
     * 房型
     */
    @Column(name = "room_type", length=50)
    private String roomType;
    /**
     * 售卖房型的id(本地酒店系统）
    */
    @Column(name = "room_id")
    private Integer roomId;
    /**
     * 房间数
     */
    @Column(name = "room_count")
    private int roomCount;
    /**
     * 入住日期
     */
    @Temporal(TemporalType.DATE)
    @Column(name = "check_in")
    private Date checkInDate;
    /**
     * 离店日期
     */
    @Temporal(TemporalType.DATE)
    @Column(name = "check_out")
    private Date checkOutDate;
    /**
     * 价格/间夜（平均价格）
     */
    private double price;
    /**
     * 底价/间夜（平均价格）
     */
    @Column(name = "bottom_price")
    private Double bottomPrice;
    /**
     * 服务费（总的服务费）
     */
    @Column(name = "service_charge")
    private double serviceCharge;
    /**
     * 间夜数
     */
    private int count;
    /**
     * 实收客户总额
     */
    @Column(name = "total_amount")
    private Double totalAmount;
    /**
     * 总成本
     */
    @Column(name = "total_cost")
    private Double totalCost;
    /**
     * 利润
     */
    private Double profit;

    /**
     * 每日房价
     */
    @OneToMany(mappedBy="orderInfo", cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
    @OrderBy("effectiveDate")
    private Set<HotelOrderPrice> prices;


    /**
     * 最晚到店时间
     */
    @Column(name = "last_arrive_time", length = 10)
    private String lastArriveTime;
    /**
     * 联系人
     */
    @Column(length=20)
    private String linkman;
    /**
     * 联系电话
     */
    @Column(name = "contact_phone", length=20)
    private String contactPhone;
    /**
     * 备注
     */
    private String remark;

    /**
     * 是否已付款
     */
    @Column(name = "be_paid", length = 1)
    private String bePaid;

    /**
     * 预订酒店的渠道
     * 0 - 人工
     * 1 - 携程代理通
     */
    @Column(name = "channel")
    private Integer reservationChannel;

    /**
     * 供应商提供的订单号
     */
    @Column(name = "supplier_order_no", length = 20)
    private String supplierOrderNo;

    /**
     * 供应商的订单状态
     * 1-待确认
     * 2-已确认-待处理
     * （保留房立即确认，供应商未处理；
     * 供应商接受订单，订单状态进入已确认-已处理;
     * 供应商拒绝订单，订单状态进入已取消-已处理（这种属于保留房不靠谱，有一定比例，分销商需要监控到，否则到店无房））
     * 3-取消中-待处理
     * （供应商确认取消，订单进入已取消-已处理；拒绝取消，订单状态还原为上一个状态；拒绝取消订单需要正常结算）
     * 4-已确认-已处理
     * 5-已取消-已处理
     */
    @Column(name = "supplier_order_status")
    private Integer supplierOrderStatus;

    /**
     * 供应商的订单确认方式
     * 1：按入住人入住
     * 2：按确认号入住
     */
    @Column(name = "supplier_confirm_type")
    private Integer supplierConfirmType;

    /**
     * 供应商提供的订单确认号
     */
    @Column(name = "supplier_confirm_no", length = 20)
    private String supplierConfirmNo;

    /**
     * 供应商提供的拒绝类型
     * 1：满房
     * 2：房价不对
     * 3：其他原因
     */
    @Column(name = "supplier_reject_type")
    private Integer supplierRejectType;

    /**
     * 供应商提供的拒单的原因
     */
    @Column(name = "supplier_reject_reason", length = 100)
    private String supplierRejectReason;

    /**
     * 供应商订单中的备注
     */
    @Column(name = "supplier_remark", length = 100)
    private String supplierRemark;

    /**
     * 订单金额是否已校验
     * null/o - 未校验
     * 1 - 校验通过
     * 4 - 校验失败, 需要人工干预
     */
    @Column(name = "price_checked")
    private Integer priceChecked;

    /**
     * 验价完成时间
     */
    @Column(name = "price_check_time")
    @Temporal(TemporalType.TIMESTAMP)
    private Date priceCheckedTime;


    /**
     * 审批信息
     */
    @Embedded
    private OrderApprovalInfo approvalInfo;

    /**
     * 通知状态: 是否发送消息提醒给相关部门
     */
    @Column(name = "notify_status")
    private Integer notifyStatus;


    public static String getSupplierOrderStatusDesc(int supplierOrderStatus) {
        switch (supplierOrderStatus) {
            case 1: return "待确认";
            case 2: return "已确认-待处理";
            case 3: return "取消中-待处理";
            case 4: return "已确认-已处理";
            case 5: return "已取消-已处理";
            default:
                return "其它";
        }
    }


    public String getPassengerName() {
        return passengerName;
    }

    public void setPassengerName(String passengerName) {
        this.passengerName = passengerName;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public double getServiceCharge() {
        return serviceCharge;
    }

    public void setServiceCharge(double serviceCharge) {
        this.serviceCharge = serviceCharge;
    }


    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public void setHotelName(String hotelName) {
        this.hotelName = hotelName;
    }

    public void setRoomType(String roomType) {
        this.roomType = roomType;
    }

    public String getRoomType() {
        return roomType;
    }

    public String getHotelName() {
        return hotelName;
    }

    public String getBePaid() {
        return bePaid;
    }

    public void setBePaid(String bePaid) {
        this.bePaid = bePaid;
    }

    public double getBottomPrice() {
        return bottomPrice == null ? 0 : bottomPrice;
    }

    public void setBottomPrice(Double bottomPrice) {
        this.bottomPrice = bottomPrice;
    }

    public double getTotalAmount() {
        return totalAmount == null ? 0 : totalAmount;
    }

    public void setTotalAmount(Double totalAmount) {
        this.totalAmount = totalAmount;
    }

    public Double getTotalCost() {
        return totalCost == null ? 0 : totalCost;
    }

    public void setTotalCost(Double totalCost) {
        this.totalCost = totalCost;
    }

    public Double getProfit() {
        return profit == null ? 0 : profit;
    }

    public void setProfit(Double profit) {
        this.profit = profit;
    }


    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public Date getCheckOutDate() {
        return checkOutDate;
    }

    public void setCheckOutDate(Date checkOutDate) {
        this.checkOutDate = checkOutDate;
    }

    public Date getCheckInDate() {
        return checkInDate;
    }

    public void setCheckInDate(Date checkInDate) {
        this.checkInDate = checkInDate;
    }

    public int getRoomCount() {
        return roomCount;
    }

    public void setRoomCount(int roomCount) {
        this.roomCount = roomCount;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public Set<HotelOrderPassenger> getPassengers() {
        if (this.passengers == null) {
            this.passengers = new HashSet<>();
        }
        return passengers;
    }

    public void setPassengers(Set<HotelOrderPassenger> passengers) {
        this.passengers = passengers;
    }

    public int getPsgCount() {
        return psgCount == null ? 0 : psgCount;
    }

    public void setPsgCount(Integer psgCount) {
        this.psgCount = psgCount;
    }

    public int getHotelId() {
        return hotelId == null ? 0 : hotelId;
    }

    public void setHotelId(Integer hotelId) {
        this.hotelId = hotelId;
    }

    public int getRoomId() {
        return roomId == null ? 0 : roomId;
    }

    public void setRoomId(Integer roomId) {
        this.roomId = roomId;
    }

    public Set<HotelOrderPrice> getPrices() {
        if (prices == null) {
            prices = new HashSet<>();
        }
        return prices;
    }

    public void setPrices(Set<HotelOrderPrice> prices) {
        this.prices = prices;
    }

    public String getLastArriveTime() {
        return lastArriveTime;
    }

    public void setLastArriveTime(String lastArriveTime) {
        this.lastArriveTime = lastArriveTime;
    }

    public String getSupplierOrderNo() {
        return supplierOrderNo;
    }

    public void setSupplierOrderNo(String supplierOrderNo) {
        this.supplierOrderNo = supplierOrderNo;
    }

    public int getSupplierOrderStatus() {
        return supplierOrderStatus == null ? 0 : supplierOrderStatus;
    }

    public void setSupplierOrderStatus(Integer supplierOrderStatus) {
        this.supplierOrderStatus = supplierOrderStatus;
    }

    public int getSupplierConfirmType() {
        return supplierConfirmType == null ? 0 : supplierConfirmType;
    }

    public void setSupplierConfirmType(Integer supplierConfirmType) {
        this.supplierConfirmType = supplierConfirmType;
    }

    public String getSupplierConfirmNo() {
        return supplierConfirmNo;
    }

    public void setSupplierConfirmNo(String supplierConfirmNo) {
        this.supplierConfirmNo = supplierConfirmNo;
    }

    public int getSupplierRejectType() {
        return supplierRejectType == null ? 0 : supplierRejectType;
    }

    public void setSupplierRejectType(Integer supplierRejectType) {
        this.supplierRejectType = supplierRejectType;
    }

    public String getSupplierRejectReason() {
        return supplierRejectReason;
    }

    public void setSupplierRejectReason(String supplierRejectReason) {
        this.supplierRejectReason = supplierRejectReason;
    }

    public String getSupplierRemark() {
        return supplierRemark;
    }

    public void setSupplierRemark(String supplierRemark) {
        this.supplierRemark = supplierRemark;
    }

    public String getLinkman() {
        return linkman;
    }

    public void setLinkman(String linkman) {
        this.linkman = linkman;
    }

    public String getContactPhone() {
        return contactPhone;
    }

    public void setContactPhone(String contactPhone) {
        this.contactPhone = contactPhone;
    }

    public OrderApprovalInfo getApprovalInfo() {
        return approvalInfo;
    }

    public void setApprovalInfo(OrderApprovalInfo approvalInfo) {
        this.approvalInfo = approvalInfo;
    }

    public int getPayStatus() {
        return payStatus == null ? 0 : payStatus;
    }

    public void setPayStatus(Integer payStatus) {
        this.payStatus = payStatus;
    }

    public int getPriceChecked() {
        return priceChecked == null ? 0 : priceChecked;
    }

    public void setPriceChecked(Integer priceChecked) {
        this.priceChecked = priceChecked;
    }

    public Date getPriceCheckedTime() {
        return priceCheckedTime;
    }

    public void setPriceCheckedTime(Date priceCheckedTime) {
        this.priceCheckedTime = priceCheckedTime;
    }

    public Integer getCityId() {
        return cityId;
    }

    public void setCityId(Integer cityId) {
        this.cityId = cityId;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public Integer getReservationChannel() {
        return reservationChannel;
    }

    public void setReservationChannel(Integer reservationChannel) {
        this.reservationChannel = reservationChannel;
    }

    public String getHotelAddress() {
        return hotelAddress;
    }

    public void setHotelAddress(String hotelAddress) {
        this.hotelAddress = hotelAddress;
    }

    public Integer getNotifyStatus() {
        return notifyStatus;
    }

    public void setNotifyStatus(Integer notifyStatus) {
        this.notifyStatus = notifyStatus;
    }

    public String getParentOrderNo() {
        return parentOrderNo;
    }

    public void setParentOrderNo(String parentOrderNo) {
        this.parentOrderNo = parentOrderNo;
    }

    public int getHotelOrderType() {
        return hotelOrderType == null ? 0 : hotelOrderType;
    }

    public void setHotelOrderType(Integer hotelOrderType) {
        this.hotelOrderType = hotelOrderType;
    }
}
